package com.stylefeng.guns.core.base.controller;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.bo.WorkBookToZipBo;
import com.stylefeng.guns.core.base.tips.SuccessTip;
import com.stylefeng.guns.core.base.warpper.BaseControllerWarpper;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.exception.GunsExceptionEnum;
import com.stylefeng.guns.core.page.PageInfoBT;
import com.stylefeng.guns.core.support.HttpKit;
import com.stylefeng.guns.core.util.DateUtil;
import com.stylefeng.guns.core.util.FileUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @author carloszhang
 */
@Slf4j
public class BaseController {

    protected static String SUCCESS = "SUCCESS";
    protected static String ERROR = "ERROR";

    protected static String REDIRECT = "redirect:";
    protected static String FORWARD = "forward:";
    
    @Value("${guns.file-download-path}")
    private String file_download_path;   // excel文件存储路径

    protected static SuccessTip SUCCESS_TIP = new SuccessTip();

    protected HttpServletRequest getHttpServletRequest() {
        return HttpKit.getRequest();
    }

    protected HttpServletResponse getHttpServletResponse() {
        return HttpKit.getResponse();
    }

    protected HttpSession getSession() {
        return HttpKit.getRequest().getSession();
    }

    protected HttpSession getSession(Boolean flag) {
        return HttpKit.getRequest().getSession(flag);
    }

    protected String getPara(String name) {
        return HttpKit.getRequest().getParameter(name);
    }

    protected void setAttr(String name, Object value) {
        HttpKit.getRequest().setAttribute(name, value);
    }

    protected Integer getSystemInvokCount() {
        return (Integer) this.getHttpServletRequest().getServletContext().getAttribute("systemCount");
    }

    /**
     * 把service层的分页信息，封装为bootstrap table通用的分页封装
     */
    protected <T> PageInfoBT<T> packForBT(Page<T> page) {
        return new PageInfoBT<T>(page);
    }

    /**
     * 包装一个list，让list增加额外属性
     */
    protected Object warpObject(BaseControllerWarpper warpper) {
        return warpper.warp();
    }

    /**
     * 删除cookie
     */
    protected void deleteCookieByName(String cookieName) {
        Cookie[] cookies = this.getHttpServletRequest().getCookies();
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(cookieName)) {
                Cookie temp = new Cookie(cookie.getName(), "");
                temp.setMaxAge(0);
                this.getHttpServletResponse().addCookie(temp);
            }
        }
    }

    /**
     * 返回前台文件流
     *
     * @author fengshuonan
     * @date 2017年2月28日 下午2:53:19
     */
    protected ResponseEntity<byte[]> renderFile(String fileName, String filePath) {
        byte[] bytes = FileUtil.toByteArray(filePath);
        return renderFile(fileName, bytes);
    }

    /**
     * 导出excel
     *
     * @param response
     * @param workbook
     * @param downLoadFileName
     */
    protected void exportData(HttpServletResponse response, Workbook workbook, String downLoadFileName) {
        response.setHeader("content-disposition", "attachment;filename=" + downLoadFileName);
        try {
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("导出excel失败", e);
        }
    }

    /**
     * 返回前台文件流
     *
     * @author fengshuonan
     * @date 2017年2月28日 下午2:53:19
     */
    protected ResponseEntity<byte[]> renderFile(String fileName, byte[] fileBytes) {
        String dfileName = null;
        try {
            dfileName = new String(fileName.getBytes("gb2312"), "iso8859-1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        headers.setContentDispositionFormData("attachment", dfileName);
        return new ResponseEntity<byte[]>(fileBytes, headers, HttpStatus.CREATED);
    }

    protected void exportDataXlsx(HttpServletResponse response, XSSFWorkbook workbook, String downLoadFileName) {
        response.setHeader("content-disposition", "attachment;filename=" + downLoadFileName);
        try {
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("导出excel失败", e);
        }
    }

    protected void exportDataXls(HttpServletResponse response, HSSFWorkbook workbook, String downLoadFileName) {
        response.setHeader("content-disposition", "attachment;filename=" + downLoadFileName);
        try {
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("导出excel失败", e);

        }
    }

    /**
     * 导出zip
     *
     * @param response
     * @param workBookBos
     * @param zipName
     */
    protected void exportZip(HttpServletResponse response, List<WorkBookToZipBo> workBookBos, String zipName) {
        response.setHeader("content-disposition", "attachment;filename=" + zipName);
        try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
        	
        	String zipFilePath = file_download_path + "/" +DateUtil.getDays() + "/" + zipName;
        	File file = new File(zipFilePath);
        	File dir = file.getParentFile();
            if(!dir.exists()){
            	dir.mkdirs();
            }
            
        	ZipOutputStream server = new ZipOutputStream(new FileOutputStream(zipFilePath));
            for (WorkBookToZipBo data : workBookBos) {
                ZipEntry entry = new ZipEntry(data.getFileName());
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                zos.putNextEntry(entry);
                server.putNextEntry(entry);
                data.getWorkbook().write(os);
                byte[] content = os.toByteArray();
                zos.write(content);
                server.write(content);;
                zos.closeEntry();
                server.closeEntry();
            }
            
            zos.flush();
            zos.close();
            server.flush();
            server.close();
            
        } catch (Exception e) {
            log.error("导出zip失败", e);
        }
    }
    
    /**
     * input-file转化为流
     *
     * @param request  MultipartHttpServletRequest
     * @param fileName html中input框对应的file name
     * @return
     */
    protected InputStream readFileToInputStream(HttpServletRequest request, String fileName) {
        if (!(request instanceof MultipartHttpServletRequest)) {
            throw new GunsException(GunsExceptionEnum.FILE_REQUEST_ERROR);
        }
        MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = mRequest.getFile(fileName);
        byte[] fileBytes = null;
        try {
            fileBytes = file.getBytes();
        } catch (Exception e) {
            log.error("获取file失败", e);
            throw new GunsException(GunsExceptionEnum.FILE_NOT_FOUND);
        }
        if (fileBytes == null || fileBytes.length <= 0) {
            throw new GunsException(GunsExceptionEnum.FILE_NOT_FOUND);
        }
        return new ByteArrayInputStream(fileBytes);//使用内存流,不需要关闭
    }
}

